#include "ContactsServer.hh"
#include "ContactException.hh"
#include "httplib.h"

#define CONTACTS_IP "43.143.235.128"
#define CONTACTS_PORT 8085
// ContactsServer::

void ContactsServer::add()
{
    httplib::Client client(CONTACTS_IP, CONTACTS_PORT);
    // 构建请求
    add_contacts_req::AddContactsRequest request;
    buildAddContactRequest(&request);
    // 序列化
    std::string req_str;
    if (!request.SerializeToString(&req_str))
    {
        throw ContactException("add_contacts_req::AddContactsRequest error!");
    }
    // 发起请求
    auto res = client.Post("/contacts/add", req_str, "application/protobuf");
    if (!res)
    {
        std::string err_desc;
        err_desc.append("/contacts/add 链接错误！错误信息：")
            .append(httplib::to_string(res.error()));
        throw ContactException(err_desc);
    }
    // 反序列化
    add_contact_resp::AddContactResponse response;
    bool parse = response.ParseFromString(res->body);
    // 处理异常
    if (res->status != 200 && !parse)
    {
        std::string err_desc;
        err_desc.append("post '/contacts/add/' 失败：")
            .append(std::to_string(res->status))
            .append("(")
            .append(res->reason)
            .append(")");
        throw ContactException(err_desc);
    }
    else if (res->status != 200)
    {
        // 处理服务异常
        std::string err_desc;
        err_desc.append("post '/contacts/add/' 失败 ")
            .append(std::to_string(res->status))
            .append("(")
            .append(res->reason)
            .append(")  错误原因：")
            .append(response.base_resp().error_desc());
        throw ContactException(err_desc);
    }
    else if (!response.base_resp().success())
    {
        // 处理结果异常
        std::string err_desc;
        err_desc.append("post '/contacts/add/' 结果异常：")
            .append("异常原因：")
            .append(response.base_resp().error_desc());
        throw ContactException(err_desc);
    }
    // 处理
    std::cout << "---->新增联系人成功,联系人ID:" << response.uid() << std::endl;
}

void ContactsServer::del()
{
    httplib::Client client(CONTACTS_IP, CONTACTS_PORT);
    // 构建请求
    del_contact_req::DelContactRequest request;
    std::cout << "请输入要删除联系人ID:";
    std::string uid;
    std::getline(std::cin, uid);
    request.set_uid(uid);
    // 序列化
    std::string req_str;
    if (!request.SerializeToString(&req_str))
    {
        throw ContactException("del_contact_req::DelContactRequest error!");
    }
    // 发起请求
    auto res = client.Post("/contacts/add", req_str, "application/protobuf");
    if (!res)
    {
        std::string err_desc;
        err_desc.append("/contacts/add 链接错误！错误信息：")
            .append(httplib::to_string(res.error()));
        throw ContactException(err_desc);
    }
    // 反序列化
    del_contact_resp::DelContactResponse response;
    bool parse = response.ParseFromString(res->body);
    // 处理异常
    if (res->status != 200 && !parse)
    {
        std::string err_desc;
        err_desc.append("post '/contacts/del' 失败：")
            .append(std::to_string(res->status))
            .append("(")
            .append(res->reason)
            .append(")");
        throw ContactException(err_desc);
    }
    else if (res->status != 200)
    {
        // 处理服务异常
        std::string err_desc;
        err_desc.append("post '/contacts/del' 失败 ")
            .append(std::to_string(res->status))
            .append("(")
            .append(res->reason)
            .append(")  错误原因：")
            .append(response.base_resp().error_desc());
        throw ContactException(err_desc);
    }
    else if (!response.base_resp().success())
    {
        // 处理结果异常
        std::string err_desc;
        err_desc.append("post '/contacts/del' 结果异常：")
            .append("异常原因：")
            .append(response.base_resp().error_desc());
        throw ContactException(err_desc);
    }
    // 处理
    std::cout << "---->删除联系人成功,联系人ID:" << response.uid() << std::endl;
}

void ContactsServer::find_all()
{
    httplib::Client client(CONTACTS_IP, CONTACTS_PORT);
    // 构建请求 发起get请求
    auto res = client.Get("/contacts/find-all");
    if (!res)
    {
        std::string err_desc;
        err_desc.append("/contacts/find-all 链接错误！错误信息：")
            .append(httplib::to_string(res.error()));
        throw ContactException(err_desc);
    }
    // 反序列化
    find_all_contacts_resp::FindAllContactsResponse response;
    bool parse = response.ParseFromString(res->body);
    // 处理异常
    if (res->status != 200 && !parse)
    {
        std::string err_desc;
        err_desc.append("post '/contacts/find_all' 失败：")
            .append(std::to_string(res->status))
            .append("(")
            .append(res->reason)
            .append(")");
        throw ContactException(err_desc);
    }
    else if (res->status != 200)
    {
        // 处理服务异常
        std::string err_desc;
        err_desc.append("post '/contacts/find_all' 失败 ")
            .append(std::to_string(res->status))
            .append("(")
            .append(res->reason)
            .append(")  错误原因：")
            .append(response.base_resp().error_desc());
        throw ContactException(err_desc);
    }
    else if (!response.base_resp().success())
    {
        // 处理结果异常
        std::string err_desc;
        err_desc.append("post '/contacts/find_all' 结果异常：")
            .append("异常原因：")
            .append(response.base_resp().error_desc());
        throw ContactException(err_desc);
    }
    // 处理
    printFindAllContactsResponse(response);
}

void ContactsServer::find_one()
{
    httplib::Client client(CONTACTS_IP, CONTACTS_PORT);
    // 构建请求
    find_one_contact_req::FindOneContactRequest request;
    std::cout << "请输入要查找联系人ID:";
    std::string uid;
    std::getline(std::cin, uid);
    request.set_uid(uid);
    // 序列化
    std::string req_str;
    if (!request.SerializeToString(&req_str))
    {
        throw ContactException("del_contact_req::DelContactRequest error!");
    }
    // 发起请求
    auto res = client.Post("/contacts/add", req_str, "application/protobuf");
    if (!res)
    {
        std::string err_desc;
        err_desc.append("/contacts/add 链接错误！错误信息：")
            .append(httplib::to_string(res.error()));
        throw ContactException(err_desc);
    }
    // 反序列化
    find_one_contact_resp::FindOneContactResponse response;
    bool parse = response.ParseFromString(res->body);
    // 处理异常
    if (res->status != 200 && !parse)
    {
        std::string err_desc;
        err_desc.append("post '/contacts/find_one' 失败：")
            .append(std::to_string(res->status))
            .append("(")
            .append(res->reason)
            .append(")");
        throw ContactException(err_desc);
    }
    else if (res->status != 200)
    {
        // 处理服务异常
        std::string err_desc;
        err_desc.append("post '/contacts/find_one' 失败 ")
            .append(std::to_string(res->status))
            .append("(")
            .append(res->reason)
            .append(")  错误原因：")
            .append(response.base_resp().error_desc());
        throw ContactException(err_desc);
    }
    else if (!response.base_resp().success())
    {
        // 处理结果异常
        std::string err_desc;
        err_desc.append("post '/contacts/find_one' 结果异常：")
            .append("异常原因：")
            .append(response.base_resp().error_desc());
        throw ContactException(err_desc);
    }
    // 处理
    std::cout << "---->查新联系人成功,联系人ID:" << response.uid() << "的详细信息:" << std::endl;
    printFindOneContactResponse(response);
}

void ContactsServer::buildAddContactRequest(add_contacts_req::AddContactsRequest *request)
{
    std::cout << "请输入联系人姓名:";
    std::string name;
    std::getline(std::cin, name);
    request->set_name(name);

    std::cout << "请输入联系人年龄:";
    int age;
    std::cin >> age;
    request->set_age(age);
    std::cin.ignore(256, '\n');

    for (int i = 0;; i++)
    {
        std::cout << "请输入联系人电话" << i + 1 << "(只输入回车完成电话新增): ";
        std::string number;
        std::getline(std::cin, number);
        if (number.empty())
        {
            break;
        }
        add_contacts_req::AddContactsRequest_Phone *phone = request->add_phone();
        phone->set_number(number);

        std::cout << "选择此电话类型 (1、移动电话   2、固定电话) : ";
        int type;
        std::cin >> type;
        std::cin.ignore(256, '\n');
        switch (type)
        {
        case 1:
            phone->set_type(add_contacts_req::AddContactsRequest_Phone_PhoneType::AddContactsRequest_Phone_PhoneType_MP);
            break;
        case 2:
            phone->set_type(add_contacts_req::AddContactsRequest_Phone_PhoneType::AddContactsRequest_Phone_PhoneType_TEL);
            break;
        default:
            std::cout << "----非法选择，使用默认值！" << std::endl;
            break;
        }
    }
    for (int i = 0;; i++)
    {
        std::cout << "请输入备注" << i + 1 << "标题 (只输入回车完成备注新增): ";
        std::string remark_key;
        std::getline(std::cin, remark_key);
        if (remark_key.empty())
        {
            break;
        }

        std::cout << "请输入备注" << i + 1 << "内容: ";
        std::string remark_value;
        std::getline(std::cin, remark_value);
        request->mutable_remake()->insert({remark_key,remark_value});
    }
}
void ContactsServer::printFindOneContactResponse(find_one_contact_resp::FindOneContactResponse &response)
{
    std::cout << "姓名：" << response.name() << std::endl;
    std::cout << "年龄：" << response.age() << std::endl;
    for (auto& phone : response.phone()) {
        int j = 1;
        std::cout << "电话" << j++ << ": " << phone.number();
        std::cout << "  (" << phone.PhoneType_Name(phone.type()) << ")" << std::endl;
    }
    if (response.remark_size()) {
        std::cout << "备注信息: " << std::endl;
    }
    for (auto it = response.remark().cbegin(); it != response.remark().cend(); ++it) {
        std::cout << "    " << it->first << ": " << it->second << std::endl;
    }
}
// 打印所有联系人信息，但是只打印姓名和ID
void ContactsServer::printFindAllContactsResponse(find_all_contacts_resp::FindAllContactsResponse &response)
{
    if (0 == response.contacts_size())
    {
        std::cout << "暂未添加任何联系人信息" << std::endl;
        return;
    }
    for (auto contact : response.contacts())
    {
        std::cout << "联系人姓名:" << contact.name() << "联系人ID:" << contact.uid() << std::endl;
    }
}